package com.nobuyme.box.xunfei;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.media.AudioFormat;
import android.os.Bundle;
import android.util.Log;

import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SynthesizerListener;
import com.nobuyme.box.app.MyApplication;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class XunFeiSpeech {
    private String Tag = "XunFeiSpeech";
    private Context mContext;
    private SpeechSynthesizer mTTS;
    private String mVoicer;        //发音人
    private int mSpeed;            //语速
    private int mPitch;            //音调
    private int mVolume;        //音量
    private int mStream;        //播放器音频流类型
    private SharedPreferences mSharedPreferences;
    private File mCacheDir;
    public static PcmPlayer mPcmPlayer;
    private OnCompleteListener mOnCompleteListener;

    /**
     * 初始化监听。
     */
    private InitListener mTTSInitListener = new InitListener() {
        @Override
        public void onInit(int code) {
            if (code != ErrorCode.SUCCESS) {
                Log.e(Tag, "初始化失败, 错误码：" + code);
            } else {
                // 初始化成功，之后可以调用startSpeaking方法
                // 注：有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成，
                // 正确的做法是将onCreate中的startSpeaking调用移至这里
            }
        }
    };

    private SynthesizerListener mTtsListener = new SynthesizerListener() {
        @Override
        public void onSpeakBegin() {

        }

        @Override
        public void onSpeakPaused() {

        }

        @Override
        public void onSpeakResumed() {

        }

        @Override
        public void onBufferProgress(int percent, int beginPos, int endPos, String info) {

        }

        @Override
        public void onSpeakProgress(int percent, int beginPos, int endPos) {

        }

        @Override
        public void onCompleted(SpeechError error) {
            if (error != null) {
                Log.e(Tag, error.getPlainDescription(true));
            }
            mTTS.stopSpeaking();
            // 退出时释放连接
            mTTS.destroy();

            if (mOnCompleteListener != null)
                mOnCompleteListener.onComplete();
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {

        }
    };
    public XunFeiSpeech(Context context) {
        mContext = MyApplication.getAppContext();
        init();
    }

    private void init() {
        mTTS = SpeechSynthesizer.createSynthesizer(mContext, mTTSInitListener);
        mSharedPreferences = mContext.getSharedPreferences(getClass().getCanonicalName(), Context.MODE_PRIVATE);
        mVoicer = mSharedPreferences.getString("voicer", "xiaoyan");
        mSpeed = mSharedPreferences.getInt("speed", 30);
        mVolume = mSharedPreferences.getInt("volume", 80);
        mPitch = mSharedPreferences.getInt("pitch", 50);
        mStream = mSharedPreferences.getInt("stream", 3);

        mTTS.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
        mTTS.setParameter(SpeechConstant.VOICE_NAME, mVoicer);
        mTTS.setParameter(SpeechConstant.SPEED, String.valueOf(mSpeed));
        mTTS.setParameter(SpeechConstant.PITCH, String.valueOf(mPitch));
        mTTS.setParameter(SpeechConstant.VOLUME, String.valueOf(mVolume));
        mTTS.setParameter(SpeechConstant.STREAM_TYPE, String.valueOf(mStream));
        mTTS.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");

        mCacheDir = FileUtils.getIntechTTSCacheDir();//缓存路径
        if (!mCacheDir.exists()) {
            mCacheDir.mkdirs();
        }
    }

    private String getTTSCacheFileName(String text) {
        String name;
        try {
            name = String.valueOf(Utils.BKDRHash(text.getBytes("utf8")));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            name = text;
        }
        return mVoicer + "_" + String.valueOf(mSpeed) + "_" + String.valueOf(mPitch) + "_" + name + ".pcm";
    }

    /**
     * @param keyWords           查找语音数据关键词
     * @param text               需要朗读的字符串
     * @param onCompleteListener 朗读完成监听
     */

    public void speak(final String keyWords, final String text, final OnCompleteListener onCompleteListener) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //如果没有开启语音，就直接关闭
//                if (YTTSGACache.getBoolean(Constant.ISUSEVOICE_CONSTANT, false) == false){
//                    mOnCompleteListener = onCompleteListener;
//                    if (mOnCompleteListener != null)
//                        mOnCompleteListener.onComplete();
//                    return;
//                }
                mOnCompleteListener = onCompleteListener;
                String cacheDirPath = mCacheDir.getPath();

                //先从文件中查找
                if (new File(cacheDirPath + File.separator + getTTSCacheFileName(keyWords)).exists()) {
                    byte[] data = getTTSCacheFileData(cacheDirPath + File.separator + getTTSCacheFileName(keyWords));
                    if (data != null) {
                        LogE("XunFeiSpeech------>读取文件");
                        playPcm(data);
                    }
                } else {
                    Log.e(Tag, "XunFeiSpeech------>网络合成");
                    mTTS.setParameter(SpeechConstant.PARAMS, "tts_audio_path=" + cacheDirPath + File.separator + getTTSCacheFileName(keyWords));//  SpeechConstant.TTS_AUDIO_PATH
                    int code = mTTS.startSpeaking(text, mTtsListener);
                    if (code != ErrorCode.SUCCESS) {
                        Log.e(Tag, "语音合成失败,错误码: " + code);
                    }
                }
            }
        }).start();
    }

    private void LogE(String s) {
        Log.e(Tag, s + "");
    }

    private void playPcm(byte[] data) {
        if (mPcmPlayer == null) {
            Log.e(Tag, "mPcmPlayer == null");
            mPcmPlayer = new PcmPlayer(null);
        }
        PcmParam param = new PcmParam();
        param.mFrequency = 16000;
        param.mChannel = AudioFormat.CHANNEL_CONFIGURATION_MONO;
        param.mSampBit = AudioFormat.ENCODING_PCM_16BIT;
        mPcmPlayer.setPcmParam(param);
        mPcmPlayer.setDataSource(data);
        if (mPcmPlayer.prepare()) {
            mPcmPlayer.play(new PcmPlayer.OnStateChangedListener() {

                @Override
                public void onStateChanged(int state) {
                    if (state == PlayState.MPS_COMPLETE)
                        if (mOnCompleteListener != null)
                            mOnCompleteListener.onComplete();
                }
            });
        }
    }

    private byte[] getTTSCacheFileData(String filePath) {
        File file = new File(filePath);
        if (file == null) {
            return null;
        }
        FileInputStream inStream;
        try {
            inStream = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        }

        byte[] data_pack = null;
        if (inStream != null) {
            long size = file.length();
            data_pack = new byte[(int) size];
            try {
                inStream.read(data_pack);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return null;
            }
        }
        return data_pack;
    }

    public String getVoicer() {
        return mVoicer;
    }

    public void setVoicer(String mVoicer) {
        this.mVoicer = mVoicer;
        Editor editor = mSharedPreferences.edit();
        editor.putString("voicer", mVoicer);
        editor.commit();
    }

    public int getSpeed() {
        return mSpeed;
    }

    public void setSpeed(int mSpeed) {
        this.mSpeed = mSpeed;
        Editor editor = mSharedPreferences.edit();
        editor.putString("speed", String.valueOf(mSpeed));
        editor.commit();
    }

    public int getVolume() {
        return mVolume;
    }

    public void setVolume(int mVolume) {
        this.mVolume = mVolume;
        Editor editor = mSharedPreferences.edit();
        editor.putString("volume", String.valueOf(mVolume));
        editor.commit();
    }

    public int getPitch() {
        return mPitch;
    }

    public void setPitch(int mPitch) {
        this.mPitch = mPitch;
        Editor editor = mSharedPreferences.edit();
        editor.putString("pitch", String.valueOf(mPitch));
        editor.commit();
    }

    public int getStream() {
        return mStream;
    }

    public void setStream(int mStream) {
        this.mStream = mStream;
    }

    public interface OnCompleteListener {
        public void onComplete();
    }
}
